import {
  getInstanceValue,
  replaceObjToBlank,
  isExpressionOrVariable,
  checkExpressionType,
  extractTernaryVariables,
  extractNullishCoalescingVariables,
  extractOptionalChainingVariables
} from './utils/index.js'
class Watcher {
  /**
   * Watcher 类，dom收集器，当对应data值改变时触发dom更新
   * @param {*} data 当前组件对象
   * @param {*} node 当前dom节点
   * @param {*} attribute dom属性绑定
   * @param {*} template dom textContent文本值
   */
  constructor(data, node, attribute, template) {
    this.node = node;
    this.data = data;
    this.attribute = attribute;
    this.template = template;
  }
  /**
   * 非数组类 dom更新
   * @param {*} value 
   */
  update (value) {
    const attribute = this.attribute;
    const data = this.data;
    const template = this.template;
    const reg = /\{\{(.*?)\}\}/g;
    if (attribute === 'value') { // 属性值设置
      this.node[attribute] = replaceObjToBlank(value)
    } else if (
      attribute === 'innerText' ||
      attribute === 'innerHTML' ||
      attribute === 'textContent'
    ) { // 节点值设置
      let tmp = ''
      let keys = []
      // 当前字符串是变量
      if (isExpressionOrVariable(template) === 'variable') {
        const expressionType = checkExpressionType(template)
        switch (expressionType) {
          /** 三目运算符 */
          case 'ternaryOperatorPattern':
            // 去除{{}}格式外的模板
            const tmpTemplate = template.replace(reg, (matched, placeholder) => {
              const trimSpaces = placeholder.trim()// 去除空白字符
              return trimSpaces
            })
            const {
              condition,
              expr1,
              expr2
            } = extractTernaryVariables(tmpTemplate)
            const flag = getInstanceValue(condition.split('.'), data)
            if (flag) {
              // 如果表达式一 是字符串
              if (expr1.match(/'|"/g)) {
                tmp = expr1.replace(/'|"/g, '')
              // 如果表达式一 是变量
              } else {
                const transferKeys = expr1.split('.')
                tmp = getInstanceValue(transferKeys, data)
              }
            } else {
              // 如果表达式一 是字符串
              if (expr2.match(/'|"/g)) {
                tmp = expr2.replace(/'|"/g, '')
              // 如果表达式一 是变量
              } else {
                const transferKeys = expr2.split('.')
                tmp = getInstanceValue(transferKeys, data)
              }
            }
            break;
          /** 空值合并运算符 */
          case 'nullishCoalescingOperatorPattern':
            const {
              value,
              defaultValue
            } = extractNullishCoalescingVariables(curStr)
            // 赋值condition
            keys = value.split('.')
            textContent = getInstanceValue(keys, data, (property) => {
              pathArray.push(property)
            })
            initWatcher(keys, data, node, 'textContent', text) // 收集器初始化并收集相关node
            return textContent ?? defaultValue.replace(/'|"/g, '')
          /** 可选链运算符 */
          case 'optionalChainingOperatorPattern':
            const {
              obj,
              prop
            } = extractOptionalChainingVariables(curStr)
            keys = [obj, prop]
            textContent = getInstanceValue(keys, data, (property) => {
              pathArray.push(property)
            })
            break
          /** 基本数据变量或者对象变量 */
          default:
            tmp = template.replace(reg, (matched, placeholder) => {
              const trimSpaces = placeholder.trim()// 去除空白字符
              return getInstanceValue(trimSpaces.split('.'), data)
            })
            break
        }
      // 当前字符串是表达式
      } else {
        // 解析表达式
      }
      this.node[attribute] = replaceObjToBlank(tmp)
    } else if (attribute === 'style') { // 样式设置
      this.node.style.cssText = value;
    } else if (attribute === 'display') { // :show 显示与隐藏设置
      this.node.style[attribute] = value ? template : 'none'
    } else if (attribute === 'attrs') {
      const styleList = template.replace(/^{|}$/g, '').trim().split(',')
      // 处理后的样式数组
      const finalResult = []
      // 存放正则匹配结果数组
      let resultList = []
      for (let i = 0, len = styleList.length; i < len; i++) {
        const eachStyle = styleList[i];
        // 样式名
        const styleName = eachStyle.split(':')[0]
        // 样式的值
        const styleValue = eachStyle.split(':')[1]
        // es6字符模板语法
        if (styleValue.includes('`')) {
        // es5及之前的字符串拼接语法
        } else {
          const reg = /([\w.]+)\s*\+\s*'?(.*?)\s*'/
          resultList = styleValue.match(reg)
        }
        if (resultList) {
          if (resultList.length === 0 || resultList.length > 3) {
            throw new LveError('lve.js提示', '暂不兼容此写法')
          // 0: "state.progress + '%'"
          // 1: "state.progress"
          // 2: "%"
          // 暂无特殊处理，就不写出来了
          } else {
            const attributeValue = getInstanceValue(resultList[1].split('.'), data)
            finalResult.push(`${styleName}:${attributeValue}${resultList?.[2] ?? ''};`)
          }
        } else {
          finalResult.push(`${styleName}:${styleValue.replace(/\s|'/g, '')};`)
        }
      }
      this.node.setAttribute('style', finalResult.join(''));
    } else if (attribute === 'class') {
      const finalClassList = []
      const arrayClassReg = /^\[|\]$/g
      let classList = []
      if (template.match(arrayClassReg)) {
        classList = template.replace(arrayClassReg, '').split(',')
      } else {
        classList = template.split(',')
      }
      for (let i = 0, len = classList.length; i < len; i++) {
        const curClass = classList[i].replace(/'|"/g, '');
        const expressionType = checkExpressionType(curClass)
        switch (expressionType) {
          /** 三目运算符 */
          case 'ternaryOperatorPattern':
            const {
              condition,
              expr1,
              expr2
            } = extractTernaryVariables(curClass)
            const keys = condition.split('.')
            const value = getInstanceValue(keys, data)
            finalClassList.push(value ? expr1 : expr2);
            break;
          /** 普通class字符串 */
          default:
            finalClassList.push(curClass);
            break;
        }
      }
      this.node.setAttribute(attribute, finalClassList.join(' '))
    } else {
      this.node.setAttribute(attribute, value);
    }
  }
  /**
   * 数组类 dom更新
   * @param {*} value 
   */
  arrayUpdate (value, type) {
    const attribute = this.attribute;
    const template = this.template;
    const reg = /\{\{(.*?)\}\}/g;
    // 暂时只对push做处理
    if (type === 'push') {
      const node = this.node.firstElementChild.cloneNode(true)
      const attr = node.attributes
      for (let i = 0; i < attr.length; i++) {
        const name = attr.item(i).name
        if (name.indexOf('key') !== -1) { // 获取到 xx-key 索引
          const id = name.split('-')[0]
          node.setAttribute(name, value[id] ? value[id] : value)
          node[attribute] = template.replace(reg, (matched, placeholder) => {
            const keys = placeholder.split('.')
            return value[keys[keys.length - 1]]
          })
          this.node.appendChild(node)
        }
      }
    }
  }
}

export default Watcher